package samples.d2.curves 
{
	import adobe.utils.CustomActions;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.utils.setInterval;
	import samples.BaseSample;
	import shapes.shapes2D.curves.CatmullRom;
	import shapes.shapes2D.curves.CubicPath;
	import shapes.shapes2D.curves.NaturalCubic;
	import shapes.shapes2D.curves.QuadraticPath;
	import shapes.shapes2D.curves.RoundPath;
	import shapes.shapes2D.Dot;
	import shapes.shapes2D.Line;
	
	/**
	 * @author Nicolas Barradeau
	 * http://en.nicoptere.net
	 */
	public class Curves_0 extends BaseSample
	{
		
		private var points:Vector.<Point>;
		private var handles:Vector.<Handle> = new Vector.<Handle>();
		
		
		public function Curves_0() 
		{
			
			_stage.addEventListener( MouseEvent.MOUSE_DOWN, mouseHandler );
			
			interval = setInterval( update, 30 );
			update();
			
		}
		
		private function mouseHandler(e:MouseEvent):void 
		{
			if ( !( e.target is Handle ) )
			{
				var h:Handle = new Handle( _stage.mouseX, _stage.mouseY, 30 );
				handles.push( h );
				addChild( h );
			}
		}
		
		private function update():void
		{
			graphics.clear();
			graphics.lineStyle( 0, color );
			
			getPointsCoords();
			
			switch( handles.length ) 
			{
				case 0:
				case 1:
				return;

				case 2:
				drawHandles();
				break;

				case 3:
				drawHandles();
				drawCubic();
				break;

				case 4:
				drawHandles();
				drawCubic();
				drawQuadratic();
				break;

				case 5:
				drawHandles();
				drawCubic();
				drawQuadratic();
				drawNaturalCubic();
				break;
				
				case 6:
				drawHandles();
				drawCubic();
				drawQuadratic();
				drawNaturalCubic();
				drawCatmullRom();
				break;
				
				default:
				drawHandles();
				drawCubic();
				drawQuadratic();
				drawNaturalCubic();
				drawCatmullRom();
				break;
			}
			
			
		}
		
		private function findClosestPoint( points:Vector.<Point> ):void 
		{
			var dp:Point  = new Point();
			var dx:Number, dy:Number, lastDist:Number = Number.POSITIVE_INFINITY, dist:Number;
			
			for each( var p:Point in points )
			{
				dx = p.x - mouseX;
				dy = p.y - mouseY;
				dist = dx * dx + dy * dy;
				if( dist < lastDist ) 
				{
					lastDist = dist;
					dp = p;
				}
				
			}
			graphics.moveTo( mouseX, mouseY );
			graphics.lineTo( dp.x, dp.y );
			graphics.drawCircle( dp.x, dp.y, 10 );
			
		}
		
		private function drawCubic():void
		{
			getPointsCoords();
			points = CubicPath.compute( points, ( points.length > 5 ) ? true : false );
			
			graphics.lineStyle( 4, 0xFF0000 );
			graphics.moveTo( points[0].x, points[0].y );
			for each( var p:Point in points )
			{
				graphics.lineTo( p.x, p.y );
			}
			graphics.lineStyle( 2, 0xFF0000, .5 );
			findClosestPoint( points );
			
		}
		private function drawQuadratic():void
		{
			
			getPointsCoords();
			points = QuadraticPath.compute( points );
			
			graphics.lineStyle( 4, 0xFFFF00 );
			graphics.moveTo( points[0].x, points[0].y );
			for each( var p:Point in points )
			{
				graphics.lineTo( p.x, p.y );
			}
			graphics.lineStyle( 2, 0xFFFF00, .5 );
			findClosestPoint( points );
		}
		
		
		private function drawNaturalCubic():void
		{
			getPointsCoords();
			var nc:NaturalCubic = new NaturalCubic( points );
			getPointsCoords()
			nc.closed = ( points.length > 5 ) ? true : false;
			nc.steps = 10;
			graphics.lineStyle( 4, 0x003399 );
			graphics.moveTo( points[0].x, points[0].y );
			
			nc.paint( this.graphics );
			
			graphics.lineStyle( 2, 0x003399, .5 );
			findClosestPoint( nc.curveAsPoints );
			
		}
		
		private function drawCatmullRom():void
		{
			
			getPointsCoords();
			points = CatmullRom.compute( points );
			graphics.lineStyle( 4, 0x00FF00 );
			graphics.moveTo( points[0].x, points[0].y );
			for each( var p:Point in points )
			{
				graphics.lineTo( p.x, p.y );
			}
			graphics.lineStyle( 2, 0x00FF00, .5 );
			findClosestPoint( points );
		}
		
		private function drawHandles():void 
		{
			graphics.lineStyle( 2, 0x808080 );
			graphics.moveTo( handles[0].x, handles[0].y );
			for each( var h:Handle in handles )
			{
				
				graphics.lineTo( h.x, h.y );
				
			}
		}
		
		private function getPointsCoords():void 
		{
			points = new Vector.<Point>();
			for each( var h:Handle in handles )
			{
				
				points.push( new Point( h.x, h.y ) );
				
			}
		}
		
	}

}
import flash.display.Sprite;
import flash.events.MouseEvent;
class Handle extends Sprite
{
	
	public function Handle( x:Number, y:Number, size:Number = 10, color:uint = 0xFFFFFF )
	{
		this.x = x;
		this.y = y;
		graphics.beginFill( color, .25 );
		graphics.drawCircle( 0, 0, size );
		graphics.beginFill( color );
		graphics.drawCircle( 0, 0, size / 4 );
		addEventListener( MouseEvent.MOUSE_DOWN, mouseHandler );
		addEventListener( MouseEvent.MOUSE_UP, mouseHandler );
		addEventListener( MouseEvent.MOUSE_OUT, mouseHandler );
		buttonMode = true;
	}
	
	private function mouseHandler(e:MouseEvent):void 
	{
		if ( e.type == MouseEvent.MOUSE_DOWN ){ startDrag();}
		else { stopDrag() };
	}
	
}
